home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- * CLASS: MiscIconWell
- * Copyright (C) 1995 Robert Todd Thomas
- * Use is governed by the MiscKit license
- *
- * See the header file for more information.
- *
- * This object is included in the MiscKit by permission from the author
- * and its use is governed by the MiscKit license, found in the file
- * "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
- * for a list of all applicable permissions and restrictions.
- ***************************************************************************/
-
- #import <misckit/MiscString.h> // here for backward compatibility
- #import "MiscIconWell.h"
-
- /*
- * A proper implementation of versioning. If you add ivars to the class (or
- * just want to dork with the reading/writing) check out the comments tagged
- * "Archiving: READ ME". BJM 5/24/94
- */
-
- /*
- * **** Archiving: READ ME **** This is the current and defined version of the
- * class. It is used to identify what data will be written and how that will
- * happen. If the read/write stuff is modified AT ALL, this must be bumped up
- * (I always bump by one) and the other comments must be followed. Failure to
- * do so will result in palettes and nibs that cannot be read. BJM 5/24/94
- */
- #define MISC_ICON_WELL_VERSION 1
-
- @implementation MiscIconWell
-
- + initialize
- {
- if (self == [MiscIconWell class])
- {
- /*
- * **** Archiving: READ ME **** After bumping the _VERSION, it is
- * considered common practice to add a comment line indicating the new
- * version number, date, and modifier. Optionally, the reason for the
- * change. There is no need to modify the setVersion message. BJM
- * 5/24/94
- */
- // version 0: initial. (bjm)
- [[MiscIconWell class] setVersion:MISC_ICON_WELL_VERSION];
- }
-
- return self;
- }
-
-
-
- - initFrame: (const NXRect *)frameRect
- {
- [super initFrame: frameRect];
-
- filename = NULL;
- [self setAllowDoubleClickLaunch: YES];
- return self;
- }
-
-
-
- - initDragTypes
- {
- // Register to accept drags that are on the NXFilenamePboard.
- const char *const types[] = {NXFilenamePboardType};
-
- [self registerForDraggedTypes: (const char *const *)&types count: 1];
- return self;
- }
-
-
-
- - free
- {
- if (filename)
- NX_FREE (filename);
-
- return [super free];
- }
-
-
-
- - (const char *)filename
- {
- // Returns the filename that the view currently represents. If the view is
- // empty, NULL is returned.
- return (const char *)filename;
- }
-
-
-
- - setImage: (NXImage *)anImage
- {
- // Overidden from MiscDragView since you could potentially set anImage
- // to nil which would erase what was contained in the view. Therefore
- // we should check for that and free the filename if there is no image.
-
- [super setImage: anImage];
-
- if ([self image] == nil)
- if (filename && (strlen(filename)))
- {
- NX_FREE (filename);
- filename = NULL;
- }
- return self;
- }
-
-
-
- - setImageByFilename: (const char *)aFilename
- {
- // Overridden from MiscDragView so the icon representation of the file
- // is fetched instead of the image itself (likely the filename is not
- // an image). It also has a small hack that if there are more than one
- // filename that it steals that multiple.tiff from Librarian.app.
-
- // Passing aFilename as NULL essentially erases the image in the view.
- if (aFilename == NULL)
- return [super setImageByFilename: NULL];
-
- if (filename && strlen(filename))
- NX_FREE (filename);
-
- filename = NX_MALLOC (filename, char, strlen(aFilename)+1);
- strcpy (filename, aFilename);
-
- /*
- * Multiple filenames are separated by tabs. We can't use -numWords because
- * numWords checks for any NXIsSpace which includes spaces. Result: if we
- * use numWords, it treats any filename with spaces as "multiple". BJM
- * 5/24/94
- */
- if (index([self filename], '\t') != NULL)
- [super setImageByFilename: "/NextApps/Librarian.app/multiple.tiff"];
- else
- [self setImage: [ [Application workspace] getIconForFile: aFilename] ];
-
- return self;
- }
-
-
-
- - setAllowDoubleClickLaunch: (BOOL)aBool
- {
- allowDoubleClickLaunch = aBool;
- return self;
- }
-
-
-
- - (BOOL)allowDoubleClickLaunch
- {
- return allowDoubleClickLaunch;
- }
-
-
-
- - launch:sender
- {
- // Launch/open file in WS: BJM 5/24/94
- // Did not work for launching multiple files under 3.0 (and possilbly 3.x)
- // and was fixed by Stephen Fitzpatrick 07/17/94.
-
- NXPoint p;
-
- // p is supposed to be the location of the image:
- // I'm not sure what value it should be set to.
- p = bounds.origin;
-
- if (index([self filename], '\t'))
- {
- // Multiple files.
- // Make a copy of the string, and iterate through each filename,
- // replacing tabs with NULLs.
-
- char *start, *end;
- int length = strlen ([self filename]);
- char copy[length+1];
-
- strcpy(copy, [self filename]);
- start = copy;
-
- // Open the first file with animation.
- end = index(start, '\t');
- *end = '\0';
-
- // causes the animation of the icon
- [[Application workspace]
- openFile:start
- fromImage:[self image] at:&p inView:self
- ];
- start = end+1;
-
- // Now do the rest of the files without animation.
- do
- {
- end = index(start, '\t');
- if (end)
- {
- *end = '\0';
- [[Application workspace] openFile:start];
- start = end+1;
- }
- else // The last file.
- [[Application workspace] openFile:start];
- }
- while (end);
- }
- else
- {
- // There's only one file: open it with animation.
- [[Application workspace]
- openFile: [self filename]
- fromImage:[self image] at:&p inView:self
- ];
- }
-
- return self;
- }
-
-
-
- - mouseDown: (NXEvent *)theEvent
- {
- // Override mouseDown to check if the icon was double clicked. If so, then
- // launch it from workspace, else let super handle it.
-
- /*
- * Only attempt to open file if there (1) DC is allowed, (2) this is a DC
- * event, and (3) there is a file to open. BJM 5/24/94
- */
- if ([self allowDoubleClickLaunch] && theEvent->data.mouse.click == 2)
- if (filename != NULL && strlen(filename) > 0)
- return [self launch:self];
-
- [super mouseDown: theEvent];
- return self;
- }
-
-
-
- - calculateDragPoint: (NXPoint *)dragPoint andOffset: (NXPoint *)offset
- {
- // Make the dragPoint be the middle of the image, so it looks nice. This
- // is overridden from MiscDragView.
-
- dragPoint->x -= imageSize.width/2.0;
- dragPoint->y -= imageSize.width/2.0;
- return self;
- }
-
-
-
- - (BOOL)setupForSourceDrag
- {
- // Put the data on the pasteboard when a source drag takes place, and
- // also choose the image to drag.
- // ...only if there is something to drag... BJM 5/24/94
-
- if (filename != NULL && strlen(filename) > 0)
- {
- id dragPB = [self draggingPasteboard];
-
- [dragPB declareTypes:&NXFilenamePboardType num:1 owner:self];
- [dragPB writeType: NXFilenamePboard
- data: [self filename]
- length: strlen([self filename]) ];
-
- [self setDragImage: theImage];
- return YES;
- }
- return NO;
- }
-
-
-
- - (BOOL)performDragOperation: sender
- {
- // Check if an incoming dragged icon is using the NXFilenamePboardType. If
- // not, then don't accept the drag.
-
- id dragPB = [self draggingPasteboard];
- char *pbData;
- int pbLength;
-
- if ([dragPB readType: NXFilenamePboardType data: &pbData
- length: &pbLength] == nil)
- {
- // If you are ending the drag, make sure to clean up.
- [self cleanupAfterDestinationDrag];
- return NO;
- }
-
- return YES;
- }
-
-
-
- - concludeDragOperation: sender
- {
- // Take the data from the pasteboard and set the new image.
-
- id dragPB = [self draggingPasteboard];
- char *pbData;
- int pbLength;
-
- [dragPB readType: NXFilenamePboardType data: &pbData
- length: &pbLength];
- [self setImageByFilename: pbData];
- [dragPB deallocatePasteboardData: pbData length: pbLength];
-
- // Make sure to call super's implementation.
- [super concludeDragOperation: sender];
- return self;
- }
-
-
-
- /*********** Archiving *************/
-
- - read:(NXTypedStream *)stream
- {
- int version;
- id oldfilename;
-
- [super read:stream];
-
- version = NXTypedStreamClassVersion(stream, "MiscIconWell");
-
- /*
- * **** Archiving: READ ME **** This code (and its analogue in write:) is
- * critical. When you bump MISC_ICON_WELL_VERSION, copy the whole _current_
- * case ("case MISC_ICON_WELL_VERSION: ... break;"), and duplicate it.
- * Change the "MISC_ICON_WELL_VERSION" in the old case to the OLD
- * (pre-bump) version number. Now, dork the "new current" version into
- * whatever you want. See how this code can now read EITHER version out of
- * the typed stream?
- *
- * If you are adding yet another version, leave the previous versionS in
- * place. That way you can still read archived objects that are more than
- * one version old. Don't forget to take whatever actions are necessary to
- * harmonize those old values. For example, if you converted an "int" ivar
- * to "double", you'd need to (in the old version) to read the int version
- * into a temp variable, and convert it in to the double var. BJM 5/24/94
- */
- switch (version)
- {
- // filename used to be a string object
- case 0:
- oldfilename = NXReadObject (stream);
- if (oldfilename)
- {
- NX_MALLOC (filename, char, [oldfilename length]+1);
- strcpy (filename, [oldfilename stringValue]);
-
- [oldfilename free];
- }
-
- NXReadTypes (stream, "c", &allowDoubleClickLaunch);
- break;
-
- case MISC_ICON_WELL_VERSION:
- NXReadTypes (stream, "*c",
- &filename, &allowDoubleClickLaunch);
- break;
-
- default:
- NXLogError("[%s %s] - unknown version of %s in typed stream",
- [[self class] name], sel_getName(_cmd), [[self class] name]);
- break;
- }
-
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- id oldfilename = nil;
-
- [super write:stream];
-
- /*
- * **** Archiving: READ ME **** Home stretch. Now (just like read:)
- * duplicate the current case ("case MISC_ICON_WELL_VERSION: ... break;").
- * Once again, change the "MISC_ICON_WELL_VERSION" of the first one to the
- * OLD version number. Now adjust the new/current MISC_ICON_WELL_VERSION
- * (remember, you've bumped it) to the new way of writing vars. See how
- * this code (because the constant is in the switch statement) always
- * writes out ONLY the current version, but leaves the old version(s)
- * around to posterity. DO NOT DELETE THE OLD VERSIONS. Leave them to
- * clutter up the world. BJM 5/24/94
- */
- switch (MISC_ICON_WELL_VERSION)
- {
- case 0:
- NXWriteObject(stream, oldfilename);
- NXWriteTypes (stream, "c", &allowDoubleClickLaunch);
- break;
-
- case MISC_ICON_WELL_VERSION:
- NXWriteTypes (stream, "*c", &filename, &allowDoubleClickLaunch);
- break;
-
- default:
- NXLogError("[%s %s] - unknown version of %s in typed stream",
- [[self class] name], sel_getName(_cmd), [[self class] name]);
- break;
- }
-
- return self;
- }
-
- /*
- * Methods to support a stringValue - basically our filename, handled
- * just like stringValue in Control objects. (This change didn't involve
- * adding any ivars or any dorking with reading/writing, so for now I've
- * left the class version number alone.)
- * shayman
- * Aug 2 1994
- */
- - (const char *)stringValue
- {
- return [self filename];
- }
- - setStringValue:(const char *)aValue
- {
- return [self setImageByFilename:aValue];
- }
- - takeStringValueFrom:sender
- {
- if ( [sender respondsTo:@selector(stringValue)] )
- return [self setStringValue: [sender stringValue]];
- return nil;
- }
-
- @end
-
-
- /***************************************************************************
- CHANGES:
-
- Small bug fixes: BJM 5/24/94 (Bruce McKenzie, spuds@netcom.com)
- 1) changed "- (char *)filename" to "- (const char *)filename"
- 2) fixed recognition of multiple files in filename to look for tab,
- rather than "any whitespace".
- 3) fixed places where it was assumed that filename ivar was ever nil
- 4) Added proper archiving/versioning to class.
- 5) Added "- launch:sender" method
- Small fix: 07/18/94(Stephen Fitzpatrick, sfitzp@elegabalus.cs.qub.ac.uk)
- 6) launch: sender did not launch multiple files (under 3.0), but does now
- Todd Thomas (todd@avocado.supernet.ab.ca) on September 20, 1994
- 7) Removed the MiscString instance so it would have less dependencies
- when palettized.
- 8) Overrode setImage from MiscDragView since it may be nil and the
- current filename should be freed and set to NULL.
- General small bug fixes (v1.4) (Todd)
- 9) With the changes to the MiscDragView superclass, it is now
- necessary to call [self cleanupAfterDestinationDrag] if you
- stop the drag by returning NO from either prepareForDragOperation:
- or performDragOperation:.
-
- ****************************************************************************/
-